Meter analysis#

## Importing compiam to the project
import compiam

# Import extras and supress warnings to keep the tutorial clean
import os
from pprint import pprint

import warnings
warnings.filterwarnings('ignore')

Carnatic and Hindustani Music Rhyhtm datasets#

That is a precise moment to introduce the (CompMusic) Carnatic and Hindustani Rhythm Datasets. These datasets, which include audio recordings, musically-relevant metadata, and beat and meter annotations, can be downloaded from Zenodo under request and used through the mirdata dataloaders available from release 0.3.7.

Let’s initialise an instance of these datasets and browse through the available data.

cmr = compiam.load_dataset(
    "compmusic_carnatic_rhythm",
    data_home=os.path.join("../audio/mir_datasets"),
    version="full_dataset"
)
cmr
The compmusic_carnatic_rhythm dataset
----------------------------------------------------------------------------------------------------


Call the .cite method for bibtex citations.
----------------------------------------------------------------------------------------------------


CompMusic Carnatic Music Rhythm class

    Args:
        track_id (str): track id of the track
        data_home (str): Local path where the dataset is stored. default=None
            If `None`, looks for the data in the default directory, `~/mir_datasets`

    Attributes:
        audio_path (str): path to audio file
        beats_path (srt): path to beats file
        meter_path (srt): path to meter file

    Cached Properties:
        beats (BeatData): beats annotation
        meter (string): meter annotation
        mbid (string): MusicBrainz ID
        name (string): name of the recording in the dataset
        artist (string): artists name
        release (string): release name
        lead_instrument_code (string): code for the load instrument
        taala (string): taala annotation
        raaga (string): raaga annotation
        num_of_beats (int): number of beats in annotation
        num_of_samas (int): number of samas in annotation

    ----------------------------------------------------------------------------------------------------

For showcasing purposes, we include a single-track version of the (CompMusic) Carnatic Rhythm Dataset within the materials of this tutorial. This dataset is private, but can be requested and downloaded for research purposes.

Reading through the dataset details we observe the available data for the tracks in the dataloader. We will load the tracks and select the specific track we have selected for tutoring purposes. Bear in mind that you can access the list of identifiers in the dataloader with the .track_ids attribute.

track = cmr.load_tracks()["10001"]

Let’s print out the available annotations for this example track.

track.beats
BeatData(confidence, confidence_unit, position_unit, positions, time_unit, times)

BeatData is an annotation type that is used in mirata to store information related to rhythmic beats. We will print the time-steps for the first 20 annotated beats.

track.beats.times[:20]
array([ 0.627846,  1.443197,  2.184898,  2.944127,  3.732721,  4.476644,
        5.293333,  6.078821,  6.825918,  7.639819,  8.42873 ,  9.201905,
       10.168209, 10.982404, 11.784082, 12.55551 , 13.325556, 14.09551 ,
       14.858866, 15.585941])

Let’s also observe that we have the actual magnitude of these annotations clear.

track.beats.time_unit
's'

We can also observe the poisitons in the cycle (if available) that each of the beats occupy.

track.beats.positions[:20]
array([1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4])

mirdata annotations have been created aiming at providing standardized and useful data structures for MIR-related annotations. In this example we showcase the use of BeatData, but many more annotation types are included in mirdata. Make sure to check them out!.

Let’s now observe how the meter annotations looks like.

track.meter
'8/4'

Akshara pulse tracker#

We can now extract the beats (referred as akshara pulses within the context of Indian Art Music) from the input recording. Likewise the other extractors and models in compiam (if not indicated otherwise), the method for inference takes an audio path as input.

# We import the tool
from compiam.rhythm.meter import AksharaPulseTracker

# Let's initialize an instance of the tool
apt = AksharaPulseTracker()
predicted_beats = apt.extract(track.audio_path)

Let’s visualise the first 20 beat estimations.

predicted_beats[:20]
array([1.0247879 , 1.23065405, 1.3127829 , 1.47632963, 2.20208346,
       2.40224309, 2.51977275, 2.73449479, 2.90140917, 3.08973219,
       3.29537696, 3.52195812, 3.7465017 , 3.81781861, 4.03828942,
       4.82774189, 4.92245834, 5.08335718, 5.27987622, 5.85751717])

We can now use the compiam.visualisation to plot the input audio with the annotations on top.

from compiam.visualisation.audio import plot_waveform
help(plot_waveform)
Help on function plot_waveform in module compiam.visualisation.audio:

plot_waveform(path_to_audio, t1, t2, labels=None, sr=44100, filepath=None)
    TODO

We observe that the labels input variable in plot_waveforms needs to be a dict with the following format: {time-step: label}, while our estimation is basically a list of pulses. Therefore, we first need to convert the prediction into a dictionary.

predicted_beats_dict = {
    time_step: idx for idx, time_step in enumerate(predicted_beats)
}

# And we plot!
plot_waveform(
    path_to_audio=track.audio_path,
    t1=0,
    t2=5,
    labels=predicted_beats_dict,
);
1.0247879048950763:0
1.2306540519864908:1
1.3127828952509681:2
1.4763296264147416:3
2.202083458945747:4
2.402243091983678:5
2.519772750636294:6
2.7344947946999327:7
2.901409168608751:8
3.0897321852624526:9
3.2953769624835365:10
3.52195811841886:11
3.7465017000162537:12
3.8178186126347753:13
4.038289423961506:14
4.82774188586985:15
4.922458344762212:16
<Figure size 2000x500 with 0 Axes>
../_images/meter_analysis_24_2.png
import IPython.display as ipd

# Let's also listen to the input audio
ipd.Audio(
    data=track.audio[0],
    rate=track.audio[1]
)